package FIT::Runner;

use FIT::Class;
use aliased 'FIT::Runner::Options';
use aliased 'FIT::Fixture::Runner';
use aliased 'FIT::Runner::Context';

has options => (
    is       => 'ro',
    isa      => 'FIT::Runner::Options',
    handles  => [qw( make_document )],
    required => 1,
    lazy     => 1,
    coerce   => 1,
    default  => sub { Options->new_with_options },
);

has document => (
    is       => 'ro',
    isa      => 'FIT::Document',
    handles  => [qw( first_table write in_dir in_file out_dir out_file twig )],
    required => 1,
    lazy     => 1,
    default  => sub { shift->make_document },
);

has fixture_runner => (
    is       => 'ro',
    isa      => 'FIT::Fixture::Runner',
    required => 1,
    handles  => [qw( run_fixtures )],
    default  => sub { Runner->new },
);

has context => (
    is       => 'ro',
    isa      => 'FIT::Runner::Context',
    required => 1,
    handles  => [qw( unix_exit_code as_summary_text )],
    default  => sub { Context->new(runner => shift) },
);

# top level runner has no parent, runners which dont add to the tally of
# their parents have no parent as well, e.g. Fixture::eg::Examples
has parent => (is => 'ro', isa => 'FIT::Runner', weak_ref => 1);

sub run {
    print "\nStarting test: ". $self->in_file. "\n"; # TODO monitoring aspect
    $self->run_fixtures( $self->first_table );
    $self->write;
    print "Completed test: ". $self->in_file. "\n"; # TODO monitoring aspect

    print $self->as_summary_text;
    return $self->unix_exit_code;
}


=head1 NAME

FIT::Runner - run a FIT test


=head1 SYNOPSIS

    use aliased 'FIT::Runner';

    $runner = Runner->new; # read args from CLI
    $runner = Runner->new(options => { in => 'in.html', out => 'out' });

    # now run the test
    $result = $runner-run; # $result is 0 if OK else 1, unix exit code style


=head1 DESCRIPTION

Create a runner with an options hash, or it will get its options from C<ARGV>.

Run the test with C<run()>. It returns an exit code suitable for C< exit() >.

=cut

